/*
 * Licensed to the 南京汇海交通科技有限公司
 *
 * Copyright (c) 2025.
 * All rights reserved.
 *
 * 本软件属南京汇海交通科技有限公司所有，在未获得南京汇海交通科技有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.cje.toolkit.support;

import com.alibaba.fastjson.JSON;
import com.chframework.boot.cache.core.ReactiveCacheHandler;
// import com.chframework.boot.core.security.TokenHandler;
import com.chframework.boot.core.properties.TokenProperty;
import com.chframework.common.context.SpringContextHolder;
import com.cje.constant.DefaultConstant;
import com.cje.basic.pojo.bo.LoginUserBO;
import com.ruoyi.common.core.domain.model.LoginUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.core.env.Environment;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.NonNull;
import reactor.core.publisher.Mono;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.function.Function;

/**
 * 获取请求头中的token
 */
public class JwtKit {

    private static String authTokenKey;
    private static TokenProperty tokenProperty;
    private static ReactiveCacheHandler reactiveCacheHandler;

    static {
        Environment environment = SpringContextHolder.getBean(Environment.class);
        JwtKit.authTokenKey = environment.getProperty(DefaultConstant.AUTH_TOKEN_KEY, StringUtils.EMPTY);
        JwtKit.tokenProperty = SpringContextHolder.getBean(TokenProperty.class);
        JwtKit.reactiveCacheHandler = SpringContextHolder.getBean(ReactiveCacheHandler.class);
    }

    /**
     * 获取请求头中的Token
     */
    public static String getRequestHeaderToken(@NonNull ServerHttpRequest request) {
        Function<String, String> formatTokenValue = (String token) -> {
            if (StringUtils.isNotEmpty(token) && token.startsWith(DefaultConstant.TOKEN_PREFIX)) {
                token = token.replace(DefaultConstant.TOKEN_PREFIX, StringUtils.EMPTY);
            }
            return token;
        };

        // 尝试获取请求头中的token
        return Optional.ofNullable(request
                        .getHeaders()
                        .getFirst(authTokenKey))
                .orElse(StringUtils.EMPTY)
                .transform(formatTokenValue);
    }

    /**
     * 获取登录用户
     */
    public static Mono<LoginUserBO> getLoginUser(String token) {
        // Claims claims = TokenHandler.parse(token);
        Claims claims = parseToken(token);
        String uuid = claims.get(DefaultConstant.LOGIN_USER_KEY, String.class);
        String userKey = String.join(StringUtils.EMPTY, DefaultConstant.LOGIN_TOKEN_KEY, uuid);

        return reactiveCacheHandler.getValue(userKey)
                .flatMap(loginUserJson -> {
                            LoginUser loginUser = JSON.parseObject(loginUserJson, LoginUser.class);
                            LoginUserBO loginUserBO = new LoginUserBO();
                            BeanUtils.copyProperties(loginUser, loginUserBO);
                            return Mono.just(loginUserBO);
                        }
                );
    }

    /**
     * 从令牌中获取数据声明
     * <p>
     * 注意，这个方法完全是为了适配已有的项目，在framework层已经封装了一套更为规范的JWT操作API，
     * 请不要将这个方法丢到framework层!!!!!!!!!!!!!!!!!!
     *
     * @param token 令牌
     * @return 数据声明
     */
    private static Claims parseToken(String token) {
        String secret = tokenProperty.getSecretKey();
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));

        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

}
